//    entity language compiler Copyright (C) 2011 Vincent Belliard

//    This program is free software: you can redistribute it and/or modify
//    it under the terms of the GNU General Public License as published by
//    the Free Software Foundation version 3 of the License.

//    This program is distributed in the hope that it will be useful,
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//    GNU General Public License for more details.

//    You should have received a copy of the GNU General Public License
//    along with this program.  If not, see <http://www.gnu.org/licenses/>.

#define class_type_void 1
#define class_type_identifier 2
#define class_type_list 4
#define class_type_reference 5
#define class_type_vector 6
#define class_type_method 7
#define class_type_null 8
#define class_type_type 9

class T_type_method ;
class T_object_class_field ;
class T_object_class_method ;
class T_expression_call_access ;
class T_constructor ;
class T_expression_constructor_arguments ;

#define type_generate_value 0
#define type_generate_introspect 1
#define type_generate_instance 2
#define type_generate_class_reference 3
#define type_generate_instance_reference 4
#define type_generate_introspect_reference 5
#define type_generate_header_reference 6
#define type_generate_header 7
#define type_generate_introspect_object 8

class T_type : public LINK<T_type>
	{
public:
	T_entity_location location ;
	T_type(const T_entity_location &new_location) : location(new_location) {}
	virtual ~T_type() {}
	virtual int get_class(void) const = 0 ;
	virtual int is_void(void) const { return FALSE ; }
	virtual int is_null(void) const { return FALSE ; }
	virtual int is_reference(void) const { return FALSE ; }
	virtual void dump(FILE *file) const = 0 ;
	virtual void verify_semantic(T_entity_compiler *compiler, T_entity_program *program, T_scope *scope, T_type_method *method_type) {}
	virtual int verify_base_class_semantic(T_entity_compiler *compiler) { return TRUE ; }
	virtual int is_object_class(T_object_class *base_class) const { return FALSE ; }
	virtual int can_overload(const T_type *ref) const { return get_class() == ref->get_class() ; }
	virtual int is_sub_type(const T_type *ref) const { return FALSE ; }
	virtual int is_good_for_call(T_entity_program *program, const T_type *call_type) const { return get_class() == call_type->get_class() ; }
	virtual const T_object_class_field *search_field(T_entity_program *program, int direct_search, const T_string name) const { return NULL ; }
	virtual const T_object_class_method *search_call(T_entity_program *program, int direct_search, const T_string name, T_expression_call_access *call) const { return NULL ; }
	virtual const T_constructor *search_constructor(T_entity_program *program, T_expression_constructor_arguments *constructor) { return NULL ; }
	virtual T_type *highest_common_factor(T_entity_compiler *compiler, T_entity_program *program, const T_entity_location type_location, T_type *type) { return this ; }
	virtual void generate_class_name(FILE *file) const {}
	virtual void generate_type_name(FILE *file, int generate_mode) const {}
	virtual void generate_argv(FILE *file, const T_string &name) const {}
	virtual void generate_type(FILE *file) const {}
	virtual void generate_virtuals(FILE *file, T_object_class *ref) const {}
	} ;

class T_type_void : public T_type
	{
public:
	T_type_void(const T_entity_location &new_location) : T_type(new_location) {}
	virtual int get_class(void) const { return class_type_void ; }
	virtual int is_void(void) const { return TRUE ; }
	virtual void dump(FILE *file) const ;
	virtual void generate_type_name(FILE *file, int generate_mode) const ;
	} ;

class T_type_null : public T_type
	{
public:
	T_type_null(const T_entity_location &new_location) : T_type(new_location) {}
	virtual int get_class(void) const { return class_type_null ; }
	virtual int is_null(void) const { return TRUE ; }
	virtual void dump(FILE *file) const ;
	virtual void generate_type_name(FILE *file, int generate_mode) const ;
	} ;

class T_type_identifier : public T_type
	{
public:
	T_string identifier ;
	T_object_class *object_class ;
	T_type_identifier(const T_entity_location &new_location, const T_string &new_identifier) : T_type(new_location), identifier(new_identifier) { object_class = NULL ; }
	T_type_identifier(const T_entity_location &new_location, T_object_class *new_object_class) : T_type(new_location) { object_class = new_object_class ; }
	virtual int get_class(void) const { return class_type_identifier ; }
	virtual void dump(FILE *file) const ;
	virtual void verify_semantic(T_entity_compiler *compiler, T_entity_program *program, T_scope *scope, T_type_method *method_type) ;
	virtual int verify_base_class_semantic(T_entity_compiler *compiler) ;
	virtual int is_object_class(T_object_class *base_class) const ;
	virtual int can_overload(const T_type *ref) const ;
	virtual int is_sub_type(const T_type *ref) const ;
	virtual int is_good_for_call(T_entity_program *program, const T_type *call_type) const ;
	virtual const T_object_class_field *search_field(T_entity_program *program, int direct_search, const T_string name) const ;
	virtual const T_object_class_method *search_call(T_entity_program *program, int direct_search, const T_string name, T_expression_call_access *call) const ;
	virtual const T_constructor *search_constructor(T_entity_program *program, T_expression_constructor_arguments *constructor) ;
	virtual void generate_class_name(FILE *file) const ;
	virtual void generate_type_name(FILE *file, int generate_mode) const ;
	virtual void generate_argv(FILE *file, const T_string &name) const ;
	virtual void generate_type(FILE *file) const ;
	virtual void generate_virtuals(FILE *file, T_object_class *ref) const ;
	} ;

class T_type_list : public T_type
	{
public:
	int mode_weak ;
	T_type *type ;
	T_string link_name ;
	T_type_list(const T_entity_location &new_location, int new_mode_weak, T_type *new_type, const T_string &new_link_name) : T_type(new_location), link_name(new_link_name) { mode_weak = new_mode_weak ; type = new_type ; }
	virtual ~T_type_list() { delete type ; }
	virtual int get_class(void) const { return class_type_list ; }
	virtual const T_object_class_field *search_field(T_entity_program *program, int direct_search, const T_string name) const ;
	virtual const T_object_class_method *search_call(T_entity_program *program, int direct_search, const T_string name, T_expression_call_access *call) const ;
	virtual void dump(FILE *file) const ;
	virtual void verify_semantic(T_entity_compiler *compiler, T_entity_program *program, T_scope *scope, T_type_method *method_type) ;
	virtual void generate_type_name(FILE *file, int generate_mode) const ;
	virtual void generate_type(FILE *file) const ;
	} ;

class T_type_reference : public T_type
	{
public:
	int mode_weak ;
	T_type *type ;
	T_type_reference(const T_entity_location &new_location, int new_mode_weak, T_type *new_type) : T_type(new_location) { mode_weak = new_mode_weak ; type = new_type ; }
	virtual ~T_type_reference() { if (type != NULL) delete type ; }
	virtual int get_class(void) const { return class_type_reference ; }
	virtual int is_reference(void) const { return TRUE ; }
	virtual void dump(FILE *file) const ;
	virtual const T_object_class_field *search_field(T_entity_program *program, int direct_search, const T_string name) const ;
	virtual const T_object_class_method *search_call(T_entity_program *program, int direct_search, const T_string name, T_expression_call_access *call) const ;
	virtual int is_good_for_call(T_entity_program *program, const T_type *call_type) const ;
	virtual void verify_semantic(T_entity_compiler *compiler, T_entity_program *program, T_scope *scope, T_type_method *method_type) ;
	virtual void generate_type(FILE *file) const ;
	virtual void generate_type_name(FILE *file, int generate_mode) const ;
	} ;

class T_type_vector : public T_type
	{
public:
	T_type_vector(const T_entity_location &new_location) : T_type(new_location) {}
	virtual ~T_type_vector() {}
	virtual int get_class(void) const { return class_type_vector ; }
	virtual void dump(FILE *file) const ;
	virtual const T_object_class_field *search_field(T_entity_program *program, int direct_search, const T_string name) const ;
	virtual void generate_type_name(FILE *file, int generate_mode) const ;
	} ;

class T_type_type : public T_type
	{
public:
	T_type_type(const T_entity_location &new_location) : T_type(new_location) {}
	virtual ~T_type_type() {}
	virtual int get_class(void) const { return class_type_vector ; }
	virtual void dump(FILE *file) const ;
	virtual const T_object_class_field *search_field(T_entity_program *program, int direct_search, const T_string name) const ;
	virtual void generate_type_name(FILE *file, int generate_mode) const ;
	} ;

class T_type_method : public T_type
	{
public:
	T_prototype prototype ;
	T_type *returned_type ;
	int test ;
	T_type_method(const T_entity_location &new_location, int new_test) : T_type(new_location) { returned_type = NULL ; test = new_test ; }
	virtual ~T_type_method() { if (returned_type != NULL) delete returned_type ; }
	virtual int get_class(void) const { return class_type_method ; }
	int specialization(void) const { return prototype.specialization ; }
	void dump_content(FILE *file) const ;
	virtual void dump(FILE *file) const ;
	int parse(T_entity_compiler *compiler) ;
	int can_overload(const T_type_method *ref) ;
	int is_good_for_call(T_entity_program *program, T_expression_constructor_arguments *call) const ;
	virtual void verify_semantic(T_entity_compiler *compiler, T_entity_program *program, T_scope *scope, T_type_method *method_type, T_object_class *object_class) ;
	} ;
